#include "LynxSound_C.hpp"
#include "LynxSoundSource_C.hpp"

namespace Lynx
{
namespace Audio
{

Sound_C::Sound_C(SoundSource *source, bool play_looped, bool start_paused) :
    mSound(0),
    mSource(source)
{
    alGenSources(1, &mSound);

    if(mSource->is_streaming())
    {
        //
    }
    else
    {
        ((SoundSource_C*)mSource)->grab_static(this);
        ALuint buffer = ((SoundSource_C*)mSource)->get_samples_everything();
        alSourcei(mSound, AL_BUFFER, buffer);
    }
}

Sound_C::Sound_C(SoundSource *source, bool play_looped, bool start_paused, const Myth::Math::Vector3f &vec) :
    mSound(0),
    mSource(source)
{
    alGenSources(1, &mSound);
}

Sound_C::~Sound_C()
{
    alSourcei(mSound, AL_BUFFER, 0);

    if(!mSource->is_streaming())
        ((SoundSource_C*)mSource)->release_static(this);

    alDeleteSources(1, &mSound);
}

SoundSource *Sound_C::get_source(void) const
{
    return mSource;
}

void Sound_C::play(void)
{
    alSourcePlay(mSound);
}

void Sound_C::pause(void)
{
    alSourcePause(mSound);
}

void Sound_C::stop(void)
{
    alSourceStop(mSound);
}

bool Sound_C::is_finished(void) const
{
    ALint state;
    alGetSourcei(mSound, AL_SOURCE_STATE, &state);
    return state == AL_STOPPED;
}

float Sound_C::get_volume(void) const
{
    ALfloat volume;
    alGetSourcef(mSound, AL_GAIN, &volume);
    return volume;
}

void Sound_C::set_volume(float volume)
{
    alSourcef(mSound, AL_GAIN, volume);
}

bool Sound_C::is_looping(void) const
{
    ALint looping;
    alGetSourcei(mSound, AL_LOOPING, &looping);
    return looping == AL_TRUE ? true : false;
}

void Sound_C::set_looping(bool looping)
{
    alSourcei(mSound, AL_LOOPING, looping ? AL_TRUE : AL_FALSE);
}

void Sound_C::set_pitch(float pitch)
{
    alSourcef(mSound, AL_PITCH, pitch);
}

float Sound_C::get_pitch(void) const
{
    ALfloat v;
    alGetSourcef(mSound, AL_PITCH, &v);
    return v;
}

void Sound_C::set_maximum_falloff_distance(float max)
{
    alSourcef(mSound, AL_MAX_DISTANCE, max);
}

float Sound_C::get_maximum_falloff_distance(void) const
{
    ALfloat v;
    alGetSourcef(mSound, AL_MAX_DISTANCE, &v);
    return v;
}

void Sound_C::set_rolloff_factor(float factor)
{
    alSourcef(mSound, AL_ROLLOFF_FACTOR, factor);
}

float Sound_C::get_rolloff_factor(void) const
{
    ALfloat v;
    alGetSourcef(mSound, AL_ROLLOFF_FACTOR, &v);
    return v;
}

void Sound_C::set_reference_distance(float distance)
{
    alSourcef(mSound, AL_REFERENCE_DISTANCE, distance);
}

float Sound_C::get_reference_distance(void) const
{
    ALfloat v;
    alGetSourcef(mSound, AL_REFERENCE_DISTANCE, &v);
    return v;
}

void Sound_C::set_position(const Myth::Math::Vector3f &position)
{
    ALfloat v[3];
    v[0] = position.X;
    v[1] = position.Y;
    v[2] = position.Z;
    alSourcefv(mSound, AL_POSITION, v);
}

Myth::Math::Vector3f Sound_C::get_position(void) const
{
    ALfloat v[3];
    alGetSourcefv(mSound, AL_POSITION, v);
    return Myth::Math::Vector3f(v[0], v[1], v[2]);
}

void Sound_C::set_velocity(const Myth::Math::Vector3f &velocity)
{
    ALfloat v[3];
    v[0] = velocity.X;
    v[1] = velocity.Y;
    v[2] = velocity.Z;
    alSourcefv(mSound, AL_VELOCITY, v);
}

Myth::Math::Vector3f Sound_C::get_velocity(void) const
{
    ALfloat v[3];
    alGetSourcefv(mSound, AL_VELOCITY, v);
    return Myth::Math::Vector3f(v[0], v[1], v[2]);
}

ALuint Sound_C::get_internal_identifier(void) const
{
    return mSound;
}

} // namespace Audio
} // namespace Lynx
